import axios from 'axios'

const loadJS = (src) => {
  return new Promise((resolve) => {
    const script = document.createElement('script')
    script.setAttribute('type', 'text/javascript')
    script.setAttribute('src', src)
    document.getElementsByTagName('head')[0].appendChild(script) // 追加到head标签内
    script.onload = function () {
      script.onload = null
      resolve()
    }
  })
}

const convertToLocalUrl = (url) => {
  return new Promise((resolve) => {
    const { android } = window
    if (url && android) {
      const callback = (url) => {
        resolve(`https://${url}`)
      }
      const callBackName = `fn${new Date().getTime()}`
      android_call[callBackName] = callback.bind(this)
      const fileName = url.match(/[\w_.-]*?(?=[\?\#])|[\w_.-]*$/)
        ? url.match(/[\w_.-]*?(?=[\?\#])|[\w_.-]*$/)[0]
        : url
      android.downLoadAndGetServerAddress(url, fileName, callBackName)
    } else {
      resolve(url)
    }
  })
}

export class MDict {
  instance = null

  constructor(props) {
    this.init(props)
  }

  /**
   * 初始化
   * @param {*} props
   */
  async init(props) {
    const {
      fileMddPath: _fileMddPath,
      fileMdxPath: _fileMdxPath,
      onLoaded = () => {},
      onLoadProgress = () => {}
    } = props

    const [fileMddPath, fileMdxPath] = await Promise.all([
      convertToLocalUrl(_fileMddPath),
      convertToLocalUrl(_fileMdxPath)
    ])

    if (!window.require) {
      await loadJS('/assistant-student-app/static/libs/mdict-js/mdict-conf.js')
      await loadJS('/assistant-student-app/static/libs/mdict-js/mdict-require.js')

      window.define('mdict-parseXml', function () {
        return function (str) {
          return new DOMParser().parseFromString(str, 'text/xml')
        }
      })
    }
    const that = this

    // 批量下载
    const downloadFiles = (urls) => {
      if (!Array.isArray(urls)) return

      // 下载进度
      const totalProgress = {
        count: 0,
        compute: function (url, progressEvent) {
          const load = progressEvent.loaded
          const total = progressEvent.total
          const progress = (load / total) * 100
          const percentage = Math.floor(progress)
          this[`file-${url}`] = percentage / this.count

          // 汇总
          let total_progress = 0
          for (let key in this) {
            if (key.indexOf('file-') != -1) {
              total_progress += this[key]
            }
          }

          onLoadProgress(total_progress)
        }
      }

      return urls.map((url) => {
        totalProgress[`file-${url}`] = 0
        totalProgress.count++

        return axios({
          method: 'get',
          url,
          responseType: 'blob',
          onDownloadProgress(ProgressEvent) {
            totalProgress.compute(url, ProgressEvent)
          }
        })
      })
    }

    if (!fileMdxPath) {
      onLoaded()
      return
    }

    const downloadFileUrls = []
    // 下载mdd文件
    if (fileMddPath) {
      downloadFileUrls.push(fileMddPath)
    }

    // 下载mdx文件
    if (fileMdxPath) {
      downloadFileUrls.push(fileMdxPath)
    }

    Promise.all(downloadFiles(downloadFileUrls)).then((data) => {
      let fileList = []

      if (!fileMddPath) {
        // 只加载mdx文件
        const [mdxRes] = data

        const { data: blob_mdx } = mdxRes
        const file_mdx = new File([blob_mdx], 'mdict.mdx')
        fileList = [file_mdx]
      } else {
        const [mddRes, mdxRes] = data

        const { data: blob_mdd } = mddRes
        const { data: blob_mdx } = mdxRes
        const file_mdd = new File([blob_mdd], 'mdict.mdd')
        const file_mdx = new File([blob_mdx], 'mdict.mdx')
        fileList = [file_mdd, file_mdx]
      }

      window.require(
        ['jquery', 'mdict-common', 'mdict-parser', 'mdict-renderer', 'selectize'],
        function ($, MCommon, MParser, MRenderer, Selectize) {
          MParser(fileList).then((resources) => {
            const mdict = MRenderer(resources)
            const title = (resources['mdx'] || resources['mdd']).value().title || '** no title **'
            const description =
              (resources['mdx'] || resources['mdd']).value().description || '** no description **'
            that.instance = Object.assign(mdict, { title, description })
            onLoaded()
          })
        }
      )
    })
  }

  /**
   * 查找单词（获取详情）
   * @param {*} word 单词
   * @returns
   */
  lookup(word, offset) {
    return new Promise((resolve) => {
      if (!this.instance) {
        resolve(null)
        return
      }

      this.instance.lookup(word, offset).then(function ($content) {
        const contents = $content.contents()

        resolve(contents)
      })
    })
  }

  /**
   * 检索单词，返回字符串数组
   * @param {*} keyword 关键词
   * @param {*} max 最大检索数量（<=5000）
   * @returns
   */
  search(keyword, max = 5000) {
    return new Promise((resolve) => {
      if (!this.instance) {
        resolve([])
        return
      }

      this.instance.search({ phrase: keyword, max }).then(function (list) {
        if (Array.isArray(list)) {
          resolve(
            list.map(function (v) {
              return v.toString()
            })
          )
        } else {
          resolve([])
        }
      })
    })
  }

  /**
   * 发音
   * @param {*} word 汉字/英文
   */
  speak(word) {
    const { android } = window

    if (android) {
      android.tts(word + '', 1)
      return true
    } else {
      return false
    }
  }

  play(url) {
    const { android } = window

    if (android) {
      android.play(url + '', 1)
      return true
    } else {
      return false
    }
  }
}
